package com.mxy.myapplication.util;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.support.annotation.Nullable;

import com.mxy.myapplication.pojo.DownloadMissionPojo;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * @author 马晓勇的专属 http请求工具类
 * <p>
 * 2018-02-02 正式服务器接口要从http切换到https   所以接口请求工具都加入了重定向机制
 */
public class HttpUrlConnectionutil {


    /**
     * 请求超时时限
     */
    private static int timeout = 20 * 1000;

    /**
     * 是否强制信任SSL
     */
    private static final boolean IGNORE_SSL = true;

    /**
     * @param url                接口请求地址
     * @param requestContent     请求参数
     * @param requestMethodGet   是否GET请求
     * @param requestContentType 请求内容是否json格式
     * @param cookie             cookie
     * @return 服务器响应的输入流
     * @throws IOException
     */
    @Nullable
    public static InputStream getHttpResponse(String url, String requestContent,
                                              boolean requestMethodGet,
                                              boolean requestContentType, String cookie) throws IOException {

        if (url == null || "".equals(url)) {
            return null;
        }

        if (!requestMethodGet && requestContent == null) {
            return null;
        }

        HttpURLConnection connection = getHttpUrlConnection(url, requestContent,
                requestMethodGet, requestContentType, cookie);
        int stutas = connection.getResponseCode();
        if (needRedirect(stutas)) {
            //获取重定向接口地址 临时重定向和永久重定向location的大小写有区分
            String redirectUrl = connection.getHeaderField("Location");
            if (redirectUrl == null) {
                redirectUrl = connection.getHeaderField("location");
            }
            //向重定向地址重新发送请求
            HttpURLConnection redirecthttpurlc = getHttpUrlConnection(redirectUrl, requestContent
                    , requestMethodGet, requestContentType, cookie);

            int newstutas = redirecthttpurlc.getResponseCode();
            Util.print("重定向后服务器响应代码:     " + newstutas);
            if (newstutas == HttpURLConnection.HTTP_OK) {
//			Constant.setCookie(Constant.domain,httpurlc);//每次请求成功，更新cookie
                return redirecthttpurlc.getInputStream();
            } else {
                return null;
            }
        } else {
            Util.print("服务器响应代码:     " + stutas);
            if (stutas == HttpURLConnection.HTTP_OK) {
//			Constant.setCookie(Constant.domain,httpurlc);//每次请求成功，更新cookie
                return connection.getInputStream();
            } else {
                return null;
            }
        }
    }


    /**
     * @param url                接口请求地址
     * @param requestContent     请求参数
     * @param requestMethodGet   是否GET请求
     * @param requestContentType 请求内容是否json格式
     * @param cookie             cookie
     * @return HttpURLConnection
     * @throws IOException
     */
    private static HttpURLConnection getHttpUrlConnection(String url, String requestContent,
                                                          boolean requestMethodGet,
                                                          boolean requestContentType,
                                                          String cookie) throws IOException {
        if (IGNORE_SSL) {
            try {
                SSLIgnore.ignoreSsl();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
        if (requestMethodGet) {
            connection.setRequestMethod("GET");
        } else {
            connection.setRequestMethod("POST");
            connection.setDoOutput(true);
        }

        //请求参数是否json格式
        if (requestContentType) {
            connection.setRequestProperty("Content-Type", "application/json");
        }

        connection.setDoInput(true);
        connection.setRequestProperty("charset", "UTF-8");
        connection.setConnectTimeout(timeout);
        connection.setReadTimeout(timeout);
        connection.setDefaultUseCaches(false);
        //		Constant.print("cookie  :     "+cookie);
//			try {
//				httpurlc.setRequestProperty("Cookie", cookie);
//			} catch (Exception e) {
//				e.printStackTrace();
//			}//请求头加入cookie信息

        //HttpURLConnection请求参数配置完毕，建立连接
        connection.connect();
        //POST请求方式请求参数是放在请求体中
        if (!requestMethodGet) {
            //POST请求方式 请求内容可直接写入输出流
            OutputStream os = connection.getOutputStream();
            os.write(requestContent.getBytes("UTF-8"));
            os.flush();
        }
        return connection;
    }


    /**
     * 断点续传GET 方法 不能设置httpurlc.setDoOutput(true)
     *
     * @param url 请求地址   ?后面跟着参数
     * @return 服务器响应的输入流
     * @throws IOException
     */
    public static InputStream getHttpUrlConnectionBreakPoint(
            URL url, DownloadMissionPojo downloadMissionPojo) throws IOException {

        try {
            SSLIgnore.ignoreSsl();
        } catch (Exception e) {
            e.printStackTrace();
        }
        //尚未获取文件大小
        if (downloadMissionPojo.getFileSize() == 0) {
            HttpURLConnection httpurlc = (HttpURLConnection) url.openConnection();
            httpurlc.setRequestMethod("GET");
            httpurlc.setConnectTimeout(timeout);
            httpurlc.setReadTimeout(timeout);
            httpurlc.setDoInput(true);
            httpurlc.setDefaultUseCaches(false);
            httpurlc.connect();
            int stutas = httpurlc.getResponseCode();
            Util.print("服务器响应代码:     " + stutas);
            if (stutas == HttpURLConnection.HTTP_OK) {
                downloadMissionPojo.setFileSize(httpurlc.getContentLength());
                httpurlc.disconnect();
            } else {
                httpurlc.disconnect();
                return null;
            }
        }

        HttpURLConnection httpurlc = (HttpURLConnection) url.openConnection();
        httpurlc.setRequestMethod("GET");
        httpurlc.setConnectTimeout(timeout);
        httpurlc.setReadTimeout(timeout);
        httpurlc.setDoInput(true);
        httpurlc.setRequestProperty("Range",
                "bytes=" + downloadMissionPojo.getReadSize() + "-" + downloadMissionPojo.getFileSize());
        httpurlc.setDefaultUseCaches(false);
        httpurlc.connect();
        int stutas = httpurlc.getResponseCode();
        Util.print("服务器响应代码:     " + stutas);
        if (stutas == HttpURLConnection.HTTP_PARTIAL) {
            return httpurlc.getInputStream();
        } else {
            return null;
        }
    }


    /**
     * ①如果要从网络中下载文件时，我们知道网络是不稳定的，
     * 也就是说网络下载时，read()方法是阻塞的，说明这时我们用inputStream.available()获取不到文件的总大小。
     * 此时就需要通过 HttpURLConnection httpconn =(HttpURLConnection)url.openConnection();
     * 然后 httpconn.getContentLength();//获取文件长度 来获取文件的大小。
     * ②如果是本地文件的话，用此方法就返回实际文件的大小。
     * ③这个方法其实是通过文件描述符获取文件的总大小，而并不是事先将磁盘上的文件数据全部读入流中，再获取文件总大小。
     * <p>
     * 流转字符串 utf-8
     */
    public static String convertStreamToStringUtf8(InputStream is) throws IOException {
        StringBuilder sb = new StringBuilder();
        String line;
        BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
        try {
            while ((line = br.readLine()) != null) {
                sb.append(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        br.close();
        is.close();
        return sb.toString();
    }


    /**
     * 流转字节数组  生成图片
     * 图片在不清楚分辨率的情况下不能直接加载，必须先经过压缩处理，才能使用
     *
     * @param is 输入流
     * @return 图像对象
     */
    public static Bitmap convertStreamToBitmap(InputStream is) {
        return BitmapFactory.decodeStream(is);
    }

    /**
     * @param status 请求返回值
     * @return 是否需要重定向
     */
    private static boolean needRedirect(int status) {
        if (status == HttpURLConnection.HTTP_OK) {
            return false;
        } else {
            return status == HttpURLConnection.HTTP_MOVED_PERM ||
                    status == HttpURLConnection.HTTP_MOVED_TEMP ||
                    status == HttpURLConnection.HTTP_SEE_OTHER;
        }
    }
}